#include "procedurewidget.h"
#include "ui_procedurewidget.h"
#include "imageenhancethread.h"
#include "../../ImageAcquisitor/global.h"

#include <QDir>
#include <QFile>
#include <QJsonObject>
#include <QSettings>
#include <QPixmap>

ProcedureWidget::ProcedureWidget(QWidget *parent) :
    ieImg(0),
    m_proc(0),
    m_userData(0),
    iet(new ImageEnhanceThread(this)),
    QWidget(parent),
    ui(new Ui::ProcedureWidget)
{
    ui->setupUi(this);
    init();
}

ProcedureWidget::~ProcedureWidget()
{
    if (iet->isRunning())
        iet->wait(5000);
    delete[] ieImg;
    ieImg = 0;
    delete ui;
}

void ProcedureWidget::init()
{
    connect(iet, SIGNAL(resultReady(int,QString)), this, SLOT(onImageEnhanced(int,QString)));
    connect(ui->bodyView, SIGNAL(bodyPartChanged(QString)), this, SLOT(onBodyPartChanged(QString)));
    connect(ui->examList, SIGNAL(itemSelectionChanged()), this, SLOT(onExamChanged()));
    connect(ui->vposList, SIGNAL(itemSelectionChanged()), this, SLOT(onVPosChanged()));
    ui->bodyView->setBodyPart(BodyProtoGraphicsView::BP_Chest);
}

void ProcedureWidget::onImageEnhanced(int ret, const QString &err)
{
    if (m_proc) {
        QJsonObject json;
        if (!ret) {
            delete[] ieImg;
            ieImg = 0;
            json["action"] = "ShowMessage";
            json["args"] = err;
            m_proc(json, m_userData);
        }

        json["action"] = "GetEnhancedImage";
        m_proc(json, m_userData);
    }
}

void ProcedureWidget::onBodyPartChanged(const QString &part)
{
    ui->examList->clear();
    QDir dir(QCoreApplication::applicationDirPath() + "/"PLUGIN_PROCEDURE_BODYPARTS_DIR + part);
    QStringList subs = dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot);
    ui->examList->addItems(subs);
    ui->examList->setCurrentRow(0);
    /*
    if (m_proc) {
        QJsonObject json;
        json["action"] = "ShowMessage";
        json["args"] = dir.absolutePath() + " " + subs.join("/");
        m_proc(json, m_userData);
    }
    */
}

void ProcedureWidget::onExamChanged()
{
    ui->vposList->clear();
    QString exam = getCurExam();
    if (!exam.isEmpty()) {
        QDir dir(QCoreApplication::applicationDirPath() + "/"PLUGIN_PROCEDURE_BODYPARTS_DIR + ui->bodyView->currentBodyPart() + "/" + exam);
        QStringList subs = dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot);
        ui->vposList->addItems(subs);
        ui->vposList->setCurrentRow(0);

        /*
        if (m_proc) {
            QJsonObject json;
            json["action"] = "ShowMessage";
            json["args"] = dir.absolutePath() + " " + subs.join("/");
            m_proc(json, m_userData);
        }
        */
    }
}

void ProcedureWidget::onVPosChanged()
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        double kv, ma, ms, mx;
        kv = s.value(PROCEDURE_DOSE_KV).toDouble();
        ma = s.value(PROCEDURE_DOSE_MA).toDouble();
        ms = s.value(PROCEDURE_DOSE_MS).toDouble();
        mx = s.value(PROCEDURE_DOSE_MX).toDouble();
        if (m_proc) {
            QJsonObject json;
            json["action"] = "UpdateDoseValues";
            QJsonObject p;
            p["kv"] = kv;
            p["ma"] = ma;
            p["ms"] = ms;
            p["mx"] = mx;
            json["args"] = p;
            m_proc(json, m_userData);
        }
    }

    f = getConfigFile(QStringList()<<"*.png"<<"*.jpg");
    if (!f.isEmpty()) {
        ui->iconLabel->setPixmap(QPixmap(f).scaled(ui->iconLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    }
}

void ProcedureWidget::setImage(ushort *img, int width, int height, int bits)
{
    delete[] ieImg;
    ieImg = 0;
    ieWidth = width;
    ieHeight = height;

    QString f = getConfigFile(QStringList()<<"*.iee");
    QJsonObject json;
    if (!f.isEmpty()) {
        if (iet->isRunning()) iet->wait();
        ieImg = new ushort[width * height];
        QString iee = f;
        iee.replace("/", "\\");
        iet->setParams(img, ieImg, iee, width, height, bits);
        iet->start();
        json["action"] = "ShowMessage";
        json["args"] = tr("Image enhancing...");
    } else {
        json["action"] = "GetEnhancedImage";
        if (m_proc) m_proc(json, m_userData);
        json["action"] = "ShowMessage";
        json["args"] = tr("Image enhancing failed, no config file found.");
    }
    if (m_proc) m_proc(json, m_userData);
}

ushort *ProcedureWidget::getEnhancedImage(ushort *&img, int &width, int &height)
{
    img = ieImg;
    width = ieWidth;
    height = ieHeight;
    ieImg = 0;
    return img;
}

bool ProcedureWidget::getBodyPartAndViewPos(QString &part, QString &pos)
{
    part = getCurExam();
    pos = getCurVPos();
    return !(part.isEmpty() | pos.isEmpty());
}

QString ProcedureWidget::getConfigFile(const QStringList &filters) const
{
    QString pos = QCoreApplication::applicationDirPath() + "/"PLUGIN_PROCEDURE_BODYPARTS_DIR + ui->bodyView->currentBodyPart() + "/" + getCurExam() + "/" + getCurVPos();
    QDir dir(pos);
    QStringList subs = dir.entryList(filters, QDir::Files);
    return subs.isEmpty()?"":dir.absoluteFilePath(subs.first());
}

bool ProcedureWidget::setDoseValues(const double &kv, const double &ma, const double &ms, const double &mx)
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        s.setValue(PROCEDURE_DOSE_KV, kv);
        s.setValue(PROCEDURE_DOSE_MA, ma);
        s.setValue(PROCEDURE_DOSE_MS, ms);
        s.setValue(PROCEDURE_DOSE_MX, mx);
        return true;
    }
    return false;
}

bool ProcedureWidget::getDoseValues(double &kv, double &ma, double &ms, double &mx) const
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        kv = s.value(PROCEDURE_DOSE_KV).toDouble();
        ma = s.value(PROCEDURE_DOSE_MA).toDouble();
        ms = s.value(PROCEDURE_DOSE_MS).toDouble();
        mx = s.value(PROCEDURE_DOSE_MX).toDouble();
        return true;
    }
    return false;
}

bool ProcedureWidget::getWindow(double &center, double width) const
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        center = s.value(PROCEDURE_WINDOW_CENTER).toDouble();
        width = s.value(PROCEDURE_WINDOW_WIDTH).toDouble();
        return true;
    }
    return false;
}

bool ProcedureWidget::setWindow(const double &center, const double &width)
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        s.setValue(PROCEDURE_WINDOW_CENTER, center);
        s.setValue(PROCEDURE_WINDOW_WIDTH, width);
        return true;
    }
    return false;
}

bool ProcedureWidget::getClipRect(QRect &rect) const
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        rect.setLeft(s.value(PROCEDURE_CLIP_LEFT).toInt());
        rect.setTop(s.value(PROCEDURE_CLIP_TOP).toInt());
        rect.setRight(s.value(PROCEDURE_CLIP_RIGHT).toInt());
        rect.setBottom(s.value(PROCEDURE_CLIP_BOTTOM).toInt());
        return true;
    }
    return false;
}

bool ProcedureWidget::setClipRect(const QRect &rect)
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        s.setValue(PROCEDURE_CLIP_LEFT, rect.left());
        s.setValue(PROCEDURE_CLIP_TOP, rect.top());
        s.setValue(PROCEDURE_CLIP_RIGHT, rect.right());
        s.setValue(PROCEDURE_CLIP_BOTTOM, rect.bottom());
        return true;
    }
    return false;
}

bool ProcedureWidget::getTransform(bool &rl, bool &rr, bool &fh, bool &fv) const
{
    QString f = getConfigFile(QStringList()<<"*.ini");
    if (!f.isEmpty()) {
        QSettings s(f, QSettings::IniFormat);
        s.setIniCodec(QSETTINGS_CODEC_NAME);
        rl = s.value(PROCEDURE_TRANSFORM_ROTATELEFT).toBool();
        rr = s.value(PROCEDURE_TRANSFORM_ROTATERIGHT).toBool();
        fh = s.value(PROCEDURE_TRANSFORM_FLIPHORIZONTAL).toBool();
        fv = s.value(PROCEDURE_TRANSFORM_FLIPVERTICAL).toBool();
        return true;
    }
    return false;
}

QString ProcedureWidget::getCurExam() const
{
    QList<QListWidgetItem*> is = ui->examList->selectedItems();
    if (!is.isEmpty()) return is.first()->text();
    return "";
}

QString ProcedureWidget::getCurVPos() const
{
    QList<QListWidgetItem*> is = ui->vposList->selectedItems();
    if (!is.isEmpty()) return is.first()->text();
    return "";
}
